#include "Transform.h"

using namespace OBR;

Transform::Transform() : mat(1.0f)
{
}

Transform::Transform(float *_mat) : mat(1.0f)
{
    memcpy(this->mat.data, _mat, sizeof(float) * 12);
}

Transform::Transform(Matrix4x4f _mat) : mat(_mat)
{
}

Transform::~Transform()
{
}

Matrix4x4f Transform::getTransformMatrix()
{
    return this->mat;
}

Transform Transform::operator*(Transform &rhs)
{
    Matrix4x4f r = rhs.getTransformMatrix();
    return Transform(Matrix4x4f::matmult(this->mat, r));
}

SRTTransform::SRTTransform() : rotation(0, 0, 0, 1)
{
    this->scale = make_float3(1, 1, 1);
    this->translation = make_float3(0, 0, 0);
}

SRTTransform::SRTTransform(float3 _scale, Quaternion _rotation, float3 _translation)
    : scale(_scale), rotation(_rotation), translation(_translation)
{
}

void SRTTransform::updateMatrix()
{
    this->mat = this->rotation.getTransformMatrix();
    for (size_t r = 0; r < 3; r++)
    {
        this->mat(r, 0) *= this->scale.x;
        this->mat(r, 1) *= this->scale.y;
        this->mat(r, 2) *= this->scale.z;
    }
    mat.data[0].w = this->translation.x;
    mat.data[1].w = this->translation.y;
    mat.data[2].w = this->translation.z;
}

Matrix4x4f SRTTransform::getTransformMatrix()
{
    this->updateMatrix();
    return this->mat;
}

OptixSRTData SRTTransform::getSRTData()
{
    return {
        this->scale.x,
        0,
        0,
        0,
        this->scale.y,
        0,
        0,
        this->scale.z,
        0, // scale part NOTE: affine scaling is not supported
        this->rotation.x,
        this->rotation.y,
        this->rotation.z,
        this->rotation.w, // rotation part
        this->translation.x,
        this->translation.y,
        this->translation.z, // translation part
    };
}